package org.infinispan.server.test.util.osgi; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Dictionary; import java.util.Enumeration; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.Filter; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.osgi.util.tracker.ServiceTracker; /** * Class copied from JBoss Fuse project and modified. */ public final class ServiceLocator { public static final Long DEFAULT_TIMEOUT = 60000L; private ServiceLocator() { //Utility Class } public static <T> T getOsgiService(Class<T> type, long timeout) { return getOsgiService(type, null, timeout); } public static <T> T getOsgiService(Class<T> type) { return getOsgiService(type, null, DEFAULT_TIMEOUT); } public static <T> T getOsgiService(Class<T> type, String filter) { return getOsgiService(type, filter, DEFAULT_TIMEOUT); } public static <T> T getOsgiService(Class<T> type, String filter, long timeout) { BundleContext bundleContext = getBundleContext(); ServiceTracker tracker = null; try { String flt; if (filter != null) { if (filter.startsWith("(")) { flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")" + filter + ")"; } else { flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")(" + filter + "))"; } } else { flt = "(" + Constants.OBJECTCLASS + "=" + type.getName() + ")"; } Filter osgiFilter = FrameworkUtil.createFilter(flt); tracker = new ServiceTracker(bundleContext, osgiFilter, null); tracker.open(true); // Note that the tracker is not closed to keep the reference // This is buggy, as the service reference may change i think Object svc = type.cast(tracker.waitForService(timeout)); if (svc == null) { Dictionary<String, String> dic = bundleContext.getBundle().getHeaders(); System.err.println("Test bundle headers: " + explode(dic)); for (ServiceReference ref : asCollection(bundleContext.getAllServiceReferences(null, null))) { System.err.println("ServiceReference: " + ref); } for (ServiceReference ref : asCollection(bundleContext.getAllServiceReferences(null, flt))) { System.err.println("Filtered ServiceReference: " + ref); } throw new RuntimeException("Gave up waiting for service " + flt); } return type.cast(svc); } catch (InvalidSyntaxException e) { throw new IllegalArgumentException("Invalid filter", e); } catch (InterruptedException e) { throw new RuntimeException(e); } } /** * Returns the bundle context. */ private static BundleContext getBundleContext() { return FrameworkUtil.getBundle(ServiceLocator.class).getBundleContext(); } /** * Explode the dictionary into a ,-delimited list of key=value pairs */ private static String explode(Dictionary<String, String> dictionary) { Enumeration<String> keys = dictionary.keys(); StringBuilder result = new StringBuilder(); while (keys.hasMoreElements()) { Object key = keys.nextElement(); result.append(String.format("%s=%s", key, dictionary.get(key))); if (keys.hasMoreElements()) { result.append(", "); } } return result.toString(); } /** * Provides an iterable collection of references, even if the original array is null */ private static Collection<ServiceReference> asCollection(ServiceReference[] references) { return references != null ? Arrays.asList(references) : Collections.<ServiceReference>emptyList(); } }